package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.learning.LearningClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseFullInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.trade.OrderBasicDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.DbException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.LearningPlanDTO;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.domain.vo.LearningLessonVO;
import com.tianji.learning.domain.vo.LearningPlanPageVO;
import com.tianji.learning.domain.vo.LearningPlanVO;
import com.tianji.learning.enums.LessonStatus;
import com.tianji.learning.enums.PlanStatus;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import com.tianji.learning.service.ILearningLessonService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.DispatcherServlet;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 学生课程表 服务实现类
 * </p>
 *
 * @author yp
 * @since 2023-09-05
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class LearningLessonServiceImpl extends ServiceImpl<LearningLessonMapper, LearningLesson> implements ILearningLessonService {

    private final CourseClient courseClient;

    private final LearningLessonMapper learningLessonMapper;

    private final CatalogueClient catalogueClient;

    private final LearningClient learningClient;

    private final LearningRecordMapper recordMapper;

    /**
     * 查询学习计划和进度
     *
     * @param pageQuery
     * @return
     */
    @Override
    public LearningPlanPageVO selectRecords(PageQuery pageQuery) {
        Long userId = UserContext.getUser();
        LocalDate now = LocalDate.now();
        LocalDateTime weekBeginTime = DateUtils.getWeekBeginTime(now);
        LocalDateTime weekEndTime = DateUtils.getWeekEndTime(now);

        //查询本周完成总数量 weekFinished    SELECT count(*) FROM learning_record WHERE user_id=129 AND finished=TRUE AND finish_time >= "2023-09-04 00:00:00" AND finish_time < "2023-09-11 00:00:00"
        LambdaQueryWrapper<LearningRecord> lqw = new LambdaQueryWrapper<>();
        lqw.eq(LearningRecord::getUserId, userId)
                .eq(LearningRecord::getFinished, true)
                .ge(LearningRecord::getFinishTime, weekBeginTime)
                .lt(LearningRecord::getFinishTime, weekEndTime);
        Integer weekFinished = recordMapper.selectCount(lqw);

        //查询本周计划总数量 weekTotalPlan   SELECT SUM(week_freq) FROM learning_lesson WHERE user_id =129 AND plan_status =1 AND `status` IN(0,1,2);
        Integer weekTotalPlan = getBaseMapper().selectWeekTotalPlan(userId);

        //学习时间 和 学习频率
        Page<LearningLesson> iPage = new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize());

        Page<LearningLesson> page = lambdaQuery().eq(LearningLesson::getUserId, userId)
                .in(LearningLesson::getStatus, 0, 1, 2)
                .eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
                .orderByDesc(LearningLesson::getLatestLearnTime)
                .page(iPage);
        List<LearningLesson> lessonList = page.getRecords();
        if (CollUtils.isEmpty(lessonList)) {
            return new LearningPlanPageVO().emptyPage(iPage);
        }

        List<LearningPlanVO> planVOS = new ArrayList<>();
        for (LearningLesson lesson : lessonList) {
            //课程名称 和 课程总量
            CourseFullInfoDTO infoDTO = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);

            //本周计划学习的小节
            LambdaQueryWrapper<LearningRecord> lqwP = new LambdaQueryWrapper<>();
            lqwP.eq(LearningRecord::getLessonId, lesson.getId())
                    .eq(LearningRecord::getUserId, userId);
            Integer weekLearnedSections = recordMapper.selectCount(lqwP);

            //封装
            LearningPlanVO pageVO = BeanUtils.copyBean(lesson, LearningPlanVO.class);
            pageVO.setCourseName(infoDTO.getName());
            pageVO.setSections(infoDTO.getSectionNum());
            pageVO.setWeekLearnedSections(weekLearnedSections);

            planVOS.add(pageVO);
        }

        //封装
        LearningPlanPageVO vo = new LearningPlanPageVO();
        vo.setWeekFinished(weekFinished);
        vo.setWeekTotalPlan(weekTotalPlan);
        vo.setList(planVOS);

        return vo;
    }

    /**
     * 创建学习计划
     *
     * @param dto
     */
    @Override
    public void createLearningPlan(LearningPlanDTO dto) {
        Long courseId = dto.getCourseId();
        Integer freq = dto.getFreq();
        Long user = UserContext.getUser();

        //查询课表
        LearningLesson learningLesson = lambdaQuery().eq(LearningLesson::getUserId, user)
                .eq(LearningLesson::getCourseId, courseId)
                .one();
        if (learningLesson == null) {
            throw new DbException("课程不存在!!!");
        }
        //修改课表
        boolean update = lambdaUpdate()
                .eq(LearningLesson::getId, learningLesson.getId())
                .set(LearningLesson::getWeekFreq, freq)
                .set(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
                .update();
        if (!update) {
            throw new DbException("修改课表信息失败!!!");
        }
    }

    /**
     * 统计课程的学习人数
     *
     * @param courseId
     * @return
     */
    @Override
    public Integer countPeople(Long courseId) {
        return learningClient.countLearningLessonByCourse(courseId);
    }

    /**
     * 删除课表中的课程
     *
     * @param dto
     */
    @Override
    public void deleteLearningLesson(OrderBasicDTO dto) {
        Long userId = UserContext.getUser(); //用户id
        List<Long> courseIds = dto.getCourseIds();  //课程id
        Long orderId = dto.getOrderId(); //订单id
        LocalDateTime finishTime = dto.getFinishTime(); //订单完成时间
        //删除课程
        LambdaQueryWrapper<LearningLesson> lqw = new LambdaQueryWrapper<>();
        lqw.eq(LearningLesson::getUserId, userId).eq(LearningLesson::getCourseId, courseIds.get(0));
        learningLessonMapper.delete(lqw);
    }

    /**
     * 检查课程是否有效
     *
     * @param courseId
     * @return
     */
    @Override
    public Long qualification(Long courseId) {
        Long userId = UserContext.getUser();
        //根据userId和courseId查询课程表
        LambdaQueryWrapper<LearningLesson> lqw = new LambdaQueryWrapper<>();
        lqw.eq(LearningLesson::getUserId, userId).eq(LearningLesson::getCourseId, courseId);
        LearningLesson learningLesson = learningLessonMapper.selectOne(lqw);
        if (learningLesson == null) {
            //无课表,返回null
            return null;
        }
        //判断状态和时间是否正常
        if (learningLesson.getStatus() == LessonStatus.EXPIRED || LocalDateTime.now().isAfter(learningLesson.getExpireTime())) {
            //过期,返回null
            return null;
        }

        //根据courseId查询课程
        CourseFullInfoDTO dto = courseClient.getCourseInfoById(courseId, false, false);
        if (dto == null) {
            //无该课程,或已过期,返回null
            return null;
        }

        //一切正常,返回lessonId
        return learningLesson.getId();
    }

    /**
     * 根据id查询指定课程的学习状态
     *
     * @param courseId
     * @return
     */
    @Override
    public LearningLessonVO queryByCourseId(Long courseId) {
        Long userId = UserContext.getUser();
        //根据userId和courseId查询课程表
        LambdaQueryWrapper<LearningLesson> lqw = new LambdaQueryWrapper<>();
        lqw.eq(LearningLesson::getUserId, userId).eq(LearningLesson::getCourseId, courseId);
        LearningLesson learningLesson = learningLessonMapper.selectOne(lqw);
        if (learningLesson == null) {
            return null;
        }
        LearningLessonVO vo = BeanUtils.copyBean(learningLesson, LearningLessonVO.class);
        //根据courseId查询课程
        CourseFullInfoDTO course = courseClient.getCourseInfoById(courseId, false, false);
        if (course == null) {
            throw new DbException("课程不存在!!!");
        }
        vo.setCourseName(course.getName());
        vo.setCourseCoverUrl(course.getCoverUrl());
        vo.setSections(course.getSectionNum());
        return vo;
    }

    /**
     * 查询最近正在学习的课程
     *
     * @return
     */
    @Override
    public LearningLessonVO queryCurrent() {
        Long userId = UserContext.getUser();
        //查询最近正在学习的一门课程
        LambdaQueryWrapper<LearningLesson> lqw = new LambdaQueryWrapper<>();
        lqw.in(LearningLesson::getStatus, 1, 2, 3).eq(LearningLesson::getUserId, userId)
                .orderBy(true, false, LearningLesson::getLatestLearnTime);

        IPage<LearningLesson> page = new Page<>(1, 1);
        learningLessonMapper.selectPage(page, lqw);
        List<LearningLesson> lessonList = page.getRecords();
        if (CollUtils.isEmpty(lessonList)) {
            return null;
        }

        LearningLesson lesson = lessonList.get(0);

        LearningLessonVO vo = BeanUtils.copyBean(lesson, LearningLessonVO.class);

        //根据courseId查询课程
        CourseFullInfoDTO dto = courseClient.getCourseInfoById(lesson.getCourseId(), false, false);
        if (dto == null) {
            throw new DbException("课程不存在!!!");
        }
        vo.setCourseName(dto.getName());
        vo.setCourseCoverUrl(dto.getCoverUrl());
        vo.setSections(dto.getSectionNum());

        //查询总数
        LambdaQueryWrapper<LearningLesson> lqwr = new LambdaQueryWrapper<>();
        lqwr.eq(LearningLesson::getUserId, userId);
        Integer num = learningLessonMapper.selectCount(lqwr);
        vo.setCourseAmount(num);

        //根据 LatestSectionId 查询小节序号
        Long latestSectionId = lesson.getLatestSectionId();
        List<CataSimpleInfoDTO> cataSimpleInfoDTOS = catalogueClient.batchQueryCatalogue(List.of(latestSectionId));
        if (!CollUtils.isEmpty(cataSimpleInfoDTOS)) {
            CataSimpleInfoDTO cataSimpleInfoDTO = cataSimpleInfoDTOS.get(0);
            vo.setLatestSectionName(cataSimpleInfoDTO.getName());
            vo.setLatestSectionIndex(cataSimpleInfoDTO.getCIndex());
        }
        return vo;
    }

    /**
     * 分页查询我的课表
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<LearningLessonVO> pageList(PageQuery pageQuery) {
        Long userId = UserContext.getUser();

        LambdaQueryWrapper<LearningLesson> lqw = new LambdaQueryWrapper<>();
        lqw.eq(LearningLesson::getUserId, userId)
                .orderBy(true, !pageQuery.getIsAsc(), LearningLesson::getLatestLearnTime);
        IPage<LearningLesson> page = new Page<>(pageQuery.getPageNo(), pageQuery.getPageSize());
        learningLessonMapper.selectPage(page, lqw);

        //获取课表信息
        List<LearningLesson> lessonList = page.getRecords();
        if (CollUtils.isEmpty(lessonList)) {
            return PageDTO.empty(CollUtils.empty(page.getClass()));
        }

        //根据课程id获取课程
        List<Long> courseId = lessonList.stream().map(LearningLesson::getCourseId).collect(Collectors.toList());

        List<CourseSimpleInfoDTO> simpleInfoList = courseClient.getSimpleInfoList(courseId);
        if (CollUtils.isEmpty(simpleInfoList)) {
            throw new DbException("课程信息不存在!!!");
        }

        Map<Long, CourseSimpleInfoDTO> courseMap = simpleInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));

        //遍历课程表,封装vo
        List<LearningLessonVO> pageList = new ArrayList<>();
        for (LearningLesson learningLesson : lessonList) {
            CourseSimpleInfoDTO dto = courseMap.get(learningLesson.getCourseId());
            LearningLessonVO vo = BeanUtils.copyBean(learningLesson, LearningLessonVO.class);
            if (dto != null) {
                vo.setCourseName(dto.getName());
                vo.setCourseCoverUrl(dto.getCoverUrl());
                vo.setSections(dto.getSectionNum());
            }
            pageList.add(vo);
        }
        return new PageDTO<>(page.getTotal(), page.getPages(), pageList);
    }


    /**
     * 添加课程到课表
     *
     * @param dto
     */
    @Override
    public void addLesson(OrderBasicDTO dto) {
        List<Long> courseIds = dto.getCourseIds(); //订单包含的课程id
        Long userId = dto.getUserId();  //用户id
        Long orderId = dto.getOrderId();  //订单id
        LocalDateTime finishTime = dto.getFinishTime(); //支付完成的时间
        //根据课程id查看课程
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if (CollUtils.isEmpty(courseList)) {
            throw new DbException("订单不存在");
        }
        //将课程添加到课表中
        List<LearningLesson> learningLessons = new ArrayList<>();
        for (CourseSimpleInfoDTO course : courseList) {
            LearningLesson learningLesson = new LearningLesson();

            learningLesson.setUserId(userId);
            learningLesson.setCourseId(course.getId());
            learningLesson.setExpireTime(LocalDateTime.now().plusMonths(course.getValidDuration()));

            learningLessons.add(learningLesson);
        }
        //保存
        saveBatch(learningLessons);
    }
}
